using System;
using System.Collections.Generic;
using UnityEngine;

public class NavigationBySeveralPoints : NavigationByPoints
{
	[Serializable]
	public struct NavigationPath
	{
		public Vector3 point;

		public float speed;

		public float timeWait;

		[HideInInspector]
		public float timeRoute;
	}

	[Serializable]
	public struct Deer
	{
		public float shift;

		public Transform tr;

		[HideInInspector]
		public Vector3 lookPosition;
	}

	private const float TIME_MESSAGE_STAY = 10f;

	public Deer[] deersShift;

	public Transform parent;

	public List<NavigationPath> path = new List<NavigationPath>();

	private NavigationPath[] interPath;

	private int INTERTP_POINT_COUNT = 20;

	private int prevIndex;

	private bool isStayPointNear;

	private Vector3 lookPosition;

	[HideInInspector]
	public event Action<bool> OnStayPointNear;

	private void Awake()
	{
		if (GameController.instance.curTypeGame == TypeGame.TDM)
		{
			UnityEngine.Object.Destroy(base.transform.parent.gameObject);
		}
		if (path.Count < 1)
		{
			BCWDebug.LogError("Critical platform error! Too many points");
			base.gameObject.SetActive(false);
			return;
		}
		for (int i = 0; i < path.Count; i++)
		{
			if (path[i].speed == 0f)
			{
				BCWDebug.LogError("Critical platform error! Speed = 0");
				base.gameObject.SetActive(false);
				return;
			}
		}
		interPath = new NavigationPath[(path.Count + 1) * INTERTP_POINT_COUNT - 1];
		Vector3[] interpPath = GetInterpPath(GetLoopedPath(false));
		float speed = path[0].speed;
		interPath[0].speed = speed;
		interPath[0].timeWait = path[0].timeWait;
		interPath[0].timeRoute = 0f;
		interPath[0].point = path[0].point;
		for (int j = 1; j < interPath.Length; j++)
		{
			int num;
			if ((num = j % INTERTP_POINT_COUNT) == 0)
			{
				num = j / INTERTP_POINT_COUNT;
				if (num == path.Count)
				{
					speed = path[0].speed;
					interPath[j].timeWait = 0f;
				}
				else
				{
					speed = path[num].speed;
					interPath[j].timeWait = path[num].timeWait;
				}
			}
			else
			{
				interPath[j].timeWait = 0f;
			}
			interPath[j].speed = speed;
			interPath[j].point = interpPath[j];
			interPath[j].timeRoute = interPath[j - 1].timeRoute + interPath[j - 1].timeWait + Vector3.Distance(interPath[j - 1].point, interPath[j].point) / interPath[j - 1].speed;
		}
		_moveTime = interPath[interPath.Length - INTERTP_POINT_COUNT - 1].timeRoute;
	}

	protected override Vector3 CalcPositiion(float value)
	{
		while (!(interPath[prevIndex].timeRoute <= value) || !(interPath[prevIndex + 1].timeRoute >= value))
		{
			if (prevIndex++ == interPath.Length - 2)
			{
				prevIndex = 0;
			}
		}
		Vector3 vector = interPath[prevIndex + 1].point - interPath[prevIndex].point;
		float num = value - interPath[prevIndex].timeRoute - interPath[prevIndex].timeWait;
		if (num < 0f)
		{
			num = 0f;
		}
		lookPosition = interPath[prevIndex + 1].point + parent.position;
		if (!isStayPointNear && interPath[prevIndex + 1].timeWait > 0f && value + 10f > interPath[prevIndex + 1].timeRoute)
		{
			isStayPointNear = true;
			if (this.OnStayPointNear != null)
			{
				this.OnStayPointNear(true);
			}
		}
		if (isStayPointNear && interPath[prevIndex].timeWait > 0f && value - interPath[prevIndex].timeRoute > interPath[prevIndex].timeWait + 5f)
		{
			isStayPointNear = false;
			if (this.OnStayPointNear != null)
			{
				this.OnStayPointNear(false);
			}
		}
		float speed = interPath[prevIndex].speed;
		for (int i = 0; i < deersShift.Length; i++)
		{
			int num2 = prevIndex;
			float num3 = interPath[prevIndex].timeRoute + interPath[prevIndex].timeWait - value;
			float num4 = value + deersShift[i].shift / speed + ((!(num3 > 0f)) ? 0f : num3);
			if (_moveTime < num4)
			{
				num4 -= _moveTime;
			}
			for (; !(interPath[num2].timeRoute <= num4) || !(interPath[num2 + 1].timeRoute >= num4); num4 += interPath[num2].timeWait)
			{
				if (num2++ == interPath.Length - 2)
				{
					num2 = 0;
				}
			}
			deersShift[i].lookPosition = interPath[num2 + 1].point + parent.position;
			Vector3 vector2 = interPath[num2 + 1].point - interPath[num2].point;
			float num5 = num4 - interPath[num2].timeRoute - interPath[num2].timeWait;
			deersShift[i].tr.position = interPath[num2].point + vector2 * (num5 / (interPath[num2 + 1].timeRoute - interPath[num2].timeRoute - interPath[num2].timeWait)) + parent.position + Vector3.up * 1.9f;
		}
		return interPath[prevIndex].point + vector * (num / (interPath[prevIndex + 1].timeRoute - interPath[prevIndex].timeRoute - interPath[prevIndex].timeWait));
	}

	private void Update()
	{
		lookPosition.y = tr.position.y;
		tr.rotation = Quaternion.Lerp(tr.rotation, Quaternion.LookRotation(lookPosition - tr.position), Time.deltaTime * 3f);
		for (int i = 0; i < deersShift.Length; i++)
		{
			Transform transform = deersShift[i].tr;
			deersShift[i].lookPosition.y = deersShift[i].tr.position.y;
			transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(deersShift[i].lookPosition - transform.position), Time.deltaTime * 3f);
		}
	}

	private Vector3[] GetInterpPath(Vector3[] path)
	{
		Vector3[] pts = PathControlPointGenerator(path);
		int num = path.Length * INTERTP_POINT_COUNT;
		Vector3[] array = new Vector3[num];
		for (int i = 0; i < num - INTERTP_POINT_COUNT; i++)
		{
			float t = (float)i / (float)num;
			array[i] = Interp(pts, t);
		}
		return array;
	}

	private Vector3[] GetLoopedPath(bool global)
	{
		Vector3[] array = new Vector3[path.Count + 1];
		for (int i = 0; i < path.Count; i++)
		{
			array[i] = path[i].point + ((!global) ? Vector3.zero : parent.transform.position);
		}
		array[path.Count] = array[0];
		return array;
	}

	private void OnDrawGizmosSelected()
	{
		if (path.Count > 0)
		{
			DrawPathHelper(GetLoopedPath(true));
		}
	}

	private void DrawPathHelper(Vector3[] path)
	{
		Vector3[] pts = PathControlPointGenerator(path);
		Gizmos.color = Color.cyan;
		Vector3 to = Interp(pts, 0f);
		int num = path.Length * INTERTP_POINT_COUNT;
		for (int i = 1; i < num - INTERTP_POINT_COUNT; i++)
		{
			float t = (float)i / (float)num;
			Vector3 vector = Interp(pts, t);
			Gizmos.DrawSphere(vector, 0.1f);
			Gizmos.DrawLine(vector, to);
			to = vector;
		}
	}

	private Vector3[] PathControlPointGenerator(Vector3[] path)
	{
		int num = 2;
		Vector3[] array = new Vector3[path.Length + num];
		Array.Copy(path, 0, array, 1, path.Length);
		array[0] = array[1] + (array[1] - array[2]);
		array[array.Length - 1] = array[array.Length - 2] + (array[array.Length - 2] - array[array.Length - 3]);
		if (array[1] == array[array.Length - 2])
		{
			Vector3[] array2 = new Vector3[array.Length];
			Array.Copy(array, array2, array.Length);
			array2[0] = array2[array2.Length - 3];
			array2[array2.Length - 1] = array2[2];
			array = new Vector3[array2.Length];
			Array.Copy(array2, array, array2.Length);
		}
		return array;
	}

	private Vector3 Interp(Vector3[] pts, float t)
	{
		int num = pts.Length - 2;
		int num2 = Mathf.Min(Mathf.FloorToInt(t * (float)num), num - 1);
		float num3 = t * (float)num - (float)num2;
		Vector3 vector = pts[num2];
		Vector3 vector2 = pts[num2 + 1];
		Vector3 vector3 = pts[num2 + 2];
		Vector3 vector4 = pts[num2 + 3];
		return 0.5f * ((-vector + 3f * vector2 - 3f * vector3 + vector4) * (num3 * num3 * num3) + (2f * vector - 5f * vector2 + 4f * vector3 - vector4) * (num3 * num3) + (-vector + vector3) * num3 + 2f * vector2);
	}
}
